package com.shareyi.baseproject.kernel.adpater.spi.sequence;

import com.shareyi.baseproject.kernel.adapter.spi.sequence.DefaultSequenceProvider;
import com.shareyi.baseproject.kernel.adapter.spi.sequence.SequenceEncodeUtils;
import com.shareyi.baseproject.kernel.adapter.spi.sequence.ShortSnowIDGenerator;
import com.shareyi.baseproject.kernel.common.spi.sequence.SequenceProvider;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
 * 序列号生成器单元测试
 *
 * @author david
 * @date 2021-08-31
 */
public class SequenceProviderTest_UT {


    /**
     * 测试雪花id生成
     */
    @Test
    public void testSnowId() {
        Long next = ShortSnowIDGenerator.next();
        Assertions.assertNotNull(next);
        System.out.println(next);
    }

    /**
     * 测试默认id生成器
     */
    @Test
    public void testDefaultSequenceProvider() {
        //如果uniqueKeeper未设置，需要抛异常
        DefaultSequenceProvider sequenceProvider = new DefaultSequenceProvider();
        Exception exception = Assertions.assertThrows(RuntimeException.class, () -> {
            sequenceProvider.next(SequenceProvider.DEFAULT_TYPE);
        });
        Assertions.assertNotNull(exception);
        Assertions.assertTrue(exception.getMessage().contains("但无集群防重保证服务"));

        //设置为false, 则允许uniqueKeeper为空
        sequenceProvider.setClusterUniqueCheckEnable(false);
        sequenceProvider.next(SequenceProvider.DEFAULT_TYPE);

        //需要uniqueKeeper，并且提供uniqueKeeper
        sequenceProvider.setClusterUniqueCheckEnable(true);
        sequenceProvider.setClusterUniqueKeeper(sequence -> true);
        sequenceProvider.next(SequenceProvider.DEFAULT_TYPE);

        //需要uniqueKeeper，并且提供uniqueKeeper, 但是每次都是false
        sequenceProvider.setClusterUniqueCheckEnable(true);
        sequenceProvider.setClusterUniqueKeeper(sequence -> false);
        Exception maxRetriesException = Assertions.assertThrows(RuntimeException.class, () -> {
            sequenceProvider.next(SequenceProvider.DEFAULT_TYPE);
        });
        Assertions.assertNotNull(maxRetriesException);
        Assertions.assertTrue(maxRetriesException.getMessage().contains("尝试多次失败"));
    }

    /**
     * 测试编码器
     */
    @Test
    public void testEncoder() {
        long sequence = ShortSnowIDGenerator.next();

        //短码编解码
        String shortScaleStr = SequenceEncodeUtils.encodeStr(sequence, SequenceEncodeUtils.DEFAULT_SHORT_SCALE);
        Assertions.assertNotNull(shortScaleStr);
        long shortScaleDecode = SequenceEncodeUtils.decodeStr(shortScaleStr, SequenceEncodeUtils.DEFAULT_SHORT_SCALE);
        Assertions.assertEquals(sequence, shortScaleDecode);

        //长码编解码
        String longScaleStr = SequenceEncodeUtils.encodeStr(sequence, SequenceEncodeUtils.DEFAULT_LONG_SCALE);
        Assertions.assertNotNull(longScaleStr);
        long longScaleDecode = SequenceEncodeUtils.decodeStr(longScaleStr, SequenceEncodeUtils.DEFAULT_LONG_SCALE);
        Assertions.assertEquals(sequence, longScaleDecode);

        Exception scaleExceedException = Assertions.assertThrows(IllegalArgumentException.class, () -> {
            SequenceEncodeUtils.encodeStr(sequence, SequenceEncodeUtils.DEFAULT_LONG_SCALE + 1);
        });
        Assertions.assertNotNull(scaleExceedException);

        Exception decodeScaleExceedException = Assertions.assertThrows(IllegalArgumentException.class, () -> {
            SequenceEncodeUtils.decodeStr(longScaleStr, SequenceEncodeUtils.DEFAULT_LONG_SCALE + 1);
        });
        Assertions.assertNotNull(decodeScaleExceedException);

        Exception decodeScaleExceedExceptionTwo = Assertions.assertThrows(IllegalArgumentException.class, () -> {
            SequenceEncodeUtils.decodeStr("abc", SequenceEncodeUtils.DEFAULT_SHORT_SCALE);
        });
        Assertions.assertNotNull(decodeScaleExceedExceptionTwo);
    }
}
